package com.youbff.task.core.init;

import java.util.Date;

import org.apache.log4j.Logger;
import org.quartz.SchedulerException;
import org.springframework.batch.core.Job;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.env.Environment;

import com.youbff.task.cluster.dto.ServerInfoDTO;
import com.youbff.task.cluster.service.ClusterService;
import com.youbff.task.constant.Constant;
import com.youbff.task.constant.TaskContext;
import com.youbff.task.constant.enums.ClusterStatus;
import com.youbff.task.core.TaskDispatch;
import com.youbff.task.core.base.LeaderCornYml;
import com.youbff.task.core.task.ClientClusterTaskListener;
import com.youbff.task.core.task.LeaderClusterTaskListener;
import com.youbff.task.utils.RedisUtil;
import com.youbff.task.utils.ServerUtils;
import com.youbff.task.utils.StringUtils;

/**
 * 初始化相关服务参数
 * @author lixuefeng
 * @email youbff@163.com
 * @time 2018年1月29日 上午11:01:01
 */
public class ApplicationStartup implements ApplicationListener<ContextRefreshedEvent> {
    private static final Logger logger = Logger.getLogger(ApplicationStartup.class);
    private ClusterService cluster;
    private RedisUtil redisUtil;
    private TaskDispatch taskDispatch;
    private Job leaderClusterTask;
    private Job clientClusterTask;
    private LeaderCornYml leaderCornYml;
    private Environment environment;
    
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        ApplicationContext context = event.getApplicationContext();
        TaskContext.setApplicationContext(context);
        initBase(context);
        learderInit();
        
    }
    
    private void initBase(ApplicationContext context){
        cluster = context.getBean(ClusterService.class);
        redisUtil = context.getBean(RedisUtil.class);
        taskDispatch = context.getBean(TaskDispatch.class);
        leaderClusterTask = (Job) context.getBean("leaderClusterTask");
        clientClusterTask = (Job) context.getBean("clientClusterTask");
        leaderCornYml = context.getBean(LeaderCornYml.class);
        environment = context.getBean(Environment.class);
    }
    
    /**
     * 初始化领导相关
     * @author lixuefeng
     * @throws SchedulerException 
     * @email youbff@163.com
     * @time 2018年1月29日 上午11:48:27
     */
    private void learderInit(){
        //服务器名称
        String serverName = StringUtils.getRandomNumber();
        //服务器器ip
        String ip = ServerUtils.getServerIp();
        ServerInfoDTO clusterDto = new ServerInfoDTO();
        clusterDto.setSerIp(ip);
        clusterDto.setPort(environment.getProperty("server.port"));
        clusterDto.setSerName(serverName);
        clusterDto.setStatus(ClusterStatus.LIVING.getValue());
        clusterDto.setAddTime(new Date());
        boolean isLeader = myIsLeader(clusterDto);
        if(isLeader){
            //自己为leader,启动集群维护任务
            clusterDto.setIsLeader(1);
            clusterDto = cluster.addClusterInfo(clusterDto);
            TaskContext.setServerInfo(clusterDto);
            try {
                taskDispatch.addJob(serverName, leaderCornYml.getMain(), leaderClusterTask, new LeaderClusterTaskListener(serverName));
            } catch (SchedulerException e) {
                logger.error("添加leader任务失败", e);
                throw new RuntimeException();
            }
            return;
        }
        //自己不是leader,跟leader通讯
        clusterDto.setIsLeader(0);
        clusterDto = cluster.addClusterInfo(clusterDto);
        TaskContext.setServerInfo(clusterDto);
        redisUtil.setHashMapValue(Constant.client_info_cache_key, serverName, clusterDto, null);
        redisUtil.setHashMapValue(Constant.client_heartbeat_cache_key, serverName, System.currentTimeMillis(), null);
        try {
            taskDispatch.addJob(serverName, leaderCornYml.getClient(), clientClusterTask, new ClientClusterTaskListener(serverName));
        } catch (SchedulerException e) {
            logger.error("添加client任务失败", e);
            throw new RuntimeException();
        }
    }
    
    /**
     * 自己是否为leader
     * @author lixuefeng
     * @email youbff@163.com
     * @time 2018年1月29日 下午2:29:20
     * @param serverName
     * @param ip
     * @return
     */
    private boolean myIsLeader(ServerInfoDTO leaderInfo){
        boolean result = redisUtil.setnx(Constant.leader_key, true);
        if(result){
            //如果当前没有leader
            leaderInfo.setIsLeader(1);
            redisUtil.set(Constant.leader_info_key, leaderInfo);
            return true;
        }
        return false;
    }

}
